﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Terminal.Advanced_AEUC_settings_controls.Settings_AUX;

namespace Terminal.Advanced_AEUC_settings_controls.Scripting
{
    /// <summary>
    /// Run time flags and script held result values of actions and funcitons
    /// </summary>
    class ScrRunTimeEnv
    {
        /// <summary>
        /// Possible conditional execution flags
        /// </summary>
        public enum CondExecMode
        {
            NORMAL,
            EXEC_IF,
            SKIP_IF,
            GOTO_ENDIF,
            GOTO_LABEL
        }
        /// <summary>
        /// Possible script run modes
        /// </summary>
        public enum RunMode
        {
            FREE_RUN,
            STEP_RUN
        }

        /// <summary>
        /// Current conditional execution flag
        /// </summary>
        public CondExecMode condExecution = CondExecMode.NORMAL;
        /// <summary>
        /// Current script running mode
        /// </summary>
        public RunMode runningMode = RunMode.FREE_RUN;

        /// <summary>
        /// Callback to update the script payload components
        /// </summary>
        public ScrMainModule.UpdateScrComponents updateComp;
        /// <summary>
        /// Callback to print out messages
        /// </summary>
        public ScriptPrint Print;
        /// <summary>
        /// Callback to execute a scipt
        /// </summary>
        public ScrMainModule.ScriptExec scrExec;
        /// <summary>
        /// Callback to generate source code from a scipt
        /// </summary>
        public ScrMainModule.ScriptExec scrSourcesify;
        /// <summary>
        /// Callback to set new scipt runtime
        /// </summary>
        public ScrMainModule.ScriptSrte scrSetRte;
        /// <summary>
        /// Storage for run time command returned results (arbitrary type)
        /// </summary>
        public object rteResult;

        /// <summary>
        /// Collection of all the breakpoints that are applied to the current script
        /// </summary>
        public List<int> breakPoints;

        #region UI progress bar access
        /// <summary>
        /// Work around to properly display progress bars for recursive script invocations
        /// </summary>
        public ProgressBars.ProgBarsHdl progBar_InvkScrWorkAround;
        /// <summary>
        /// Creates a progress bar on the script main view
        /// </summary>
        /// <param name="name">Display name for the progress bar</param>
        /// <param name="length">Units length of the progress bar</param>
        public ScrMainModule.ScriptSetUpProgBar scrSetUpProgBar;
        /// <summary>
        /// Perform a step on the script progress bar
        /// </summary>
        public ScrMainModule.ScriptStepProgBar scrStepProgBar;
        /// <summary>
        /// Hide the script progress bar
        /// </summary>
        public ScrMainModule.ScriptRemoveProgBar scrRemProgBar;
        #endregion

        #region RTE execution events
        /// <summary>
        /// Script event script done
        /// </summary>
        public event ScrMainModule.ScriptEvent OnScriptDone;
        /// <summary>
        /// Script event breakpoint reached
        /// </summary>
        public event ScrMainModule.ScriptEvent OnScriptBreakReached;
        /// <summary>
        /// Script event execution line changed
        /// </summary>
        public event ScrMainModule.ScriptEvent OnScriptExecLineChange;
        /// <summary>
        /// Script event components changed
        /// </summary>
        public event ScrMainModule.ScriptEvent OnScriptComponentsChanged;
        /// <summary>
        /// Script event done
        /// </summary>
        public event ScrMainModule.ScriptEvent OnScriptSourceGenerated;
        /// <summary>
        /// Script event terminating script module
        /// </summary>
        public event ScrMainModule.ScriptEvent OnScriptModuleTerminatig;
        /// <summary>
        /// Fire script terminating event
        /// </summary>
        public void FireScrTerminating()
        {
            if (OnScriptModuleTerminatig != null)
                OnScriptModuleTerminatig("Terminating execution");
        }
        /// <summary>
        /// Fire component update occured event
        /// </summary>
        /// <param name="errorStatus">Error status sring</param>
        public void FireCompUpdate(string errorStatus)
        {
            if (OnScriptComponentsChanged != null)
                OnScriptComponentsChanged(errorStatus);
        }
        /// <summary>
        /// Fire script exec line change event
        /// </summary>
        /// <param name="errorStatus">Error status sring</param>
        public void FireExecLineChange(string errorStatus)
        {
            if (OnScriptExecLineChange != null)
                OnScriptExecLineChange(errorStatus);
        }
        /// <summary>
        /// Fire script done event
        /// </summary>
        /// <param name="errorStatus">Error status sring</param>
        public void FireScrDone(string errorStatus)
        {
            if (OnScriptDone != null && !SilentRun)
                OnScriptDone(errorStatus);
        }
        /// <summary>
        /// Fire source generation done event
        /// </summary>
        /// <param name="errorStatus">Error status sring</param>
        public void FireScrSourceGenDone(string errorStatus)
        {
            if (OnScriptSourceGenerated != null)
                OnScriptSourceGenerated(errorStatus);
        }
        /// <summary>
        /// Fire breakpoint reached event
        /// </summary>
        /// <param name="errorStatus">Error status sring</param>
        public void FireBreakReached(string errorStatus)
        {
            if (OnScriptBreakReached != null)
                OnScriptBreakReached(errorStatus);
        }
        /// <summary>
        /// Available script events
        /// </summary>
        public enum ScrEvents
        {
            CompUpdate = 1,
            LineChange = 2,
            Done = 4,
            SourceGenDone = 8,
            BreakReached = 16,
            Terminating = 32
        }
        
        /// <summary>
        /// Copy escript event handlers to another instance
        /// </summary>
        /// <param name="nRte">Instance to receive the event handlers</param>
        public void CopyScriptEvents(ScrRunTimeEnv nRte, ScrEvents evns)
        {
            if ((evns & ScrEvents.BreakReached) == ScrEvents.BreakReached)
                nRte.OnScriptBreakReached = OnScriptBreakReached;
            if ((evns & ScrEvents.CompUpdate) == ScrEvents.CompUpdate)
                nRte.OnScriptComponentsChanged = OnScriptComponentsChanged;
            if ((evns & ScrEvents.Done) == ScrEvents.Done)
                nRte.OnScriptDone = OnScriptDone;
            if ((evns & ScrEvents.LineChange) == ScrEvents.LineChange)
                nRte.OnScriptExecLineChange = OnScriptExecLineChange;
            if ((evns & ScrEvents.Terminating) == ScrEvents.Terminating)
                nRte.OnScriptModuleTerminatig = OnScriptModuleTerminatig;
            if ((evns & ScrEvents.SourceGenDone) == ScrEvents.SourceGenDone)
                nRte.OnScriptSourceGenerated = OnScriptSourceGenerated;
        }
        #endregion

        /// <summary>
        /// Indicates if "done" message is to be fired.
        /// </summary>
        public bool SilentRun;
        /// <summary>
        /// Recursion id
        /// </summary>
        public int ScrRecId;
        /// <summary>
        /// Indicates if script execution should stop if a message has status differenet than error none
        /// </summary>
        public bool StopOnErrorMsgStatus;

        /// <summary>
        /// Current command line that is processed by the script.
        /// </summary>
        public int crntCmdLine = -1;
        /// <summary>
        /// Target command line to run the script to (apply break point when reached).
        /// </summary>
        public int trgtCmdLine;
        /// <summary>
        /// Array of command lines that will be processed. Could be updated script run time?!
        /// </summary>
        public string[] cmdLns;
        /// <summary>
        /// Generated source code of this script session or the name of the script currently being executed
        /// </summary>
        public string c_source = "C source not available";

        /// <summary>
        /// Flag indicating if the RTE is restoring after an invoke command
        /// </summary>
        public bool InvokeEnded = false;

        /// <summary>
        /// Clones the current script runtime
        /// </summary>
        /// <returns>Cloned script runtime object</returns>
        public ScrRunTimeEnv Clone()
        {
            ScrRunTimeEnv nRte = new ScrRunTimeEnv();

            nRte.condExecution = condExecution;
            nRte.Print = Print;
            nRte.rteResult = rteResult;
            nRte.runningMode = runningMode;
            nRte.updateComp = updateComp;
            nRte.crntCmdLine = crntCmdLine;
            nRte.trgtCmdLine = trgtCmdLine;
            nRte.cmdLns = cmdLns;
            nRte.scrExec = scrExec;
            nRte.scrSourcesify = scrSourcesify;
            nRte.scrSetRte = scrSetRte;
            nRte.StopOnErrorMsgStatus = StopOnErrorMsgStatus;
            nRte.c_source = c_source;
            nRte.SilentRun = SilentRun;
            nRte.StopOnErrorMsgStatus = StopOnErrorMsgStatus;

            nRte.scrSetUpProgBar = scrSetUpProgBar;
            nRte.scrStepProgBar = scrStepProgBar;
            nRte.scrRemProgBar = scrRemProgBar;

            nRte.OnScriptBreakReached = OnScriptBreakReached;
            nRte.OnScriptComponentsChanged = OnScriptComponentsChanged;
            nRte.OnScriptDone = OnScriptDone;
            nRte.OnScriptExecLineChange = OnScriptExecLineChange;
            nRte.OnScriptModuleTerminatig = OnScriptModuleTerminatig;
            nRte.OnScriptSourceGenerated = OnScriptSourceGenerated;

            nRte.breakPoints = breakPoints;

            nRte.progBar_InvkScrWorkAround = progBar_InvkScrWorkAround;

            nRte.InvokeEnded = InvokeEnded;

            return nRte;
        }
    }

    /// <summary>
    /// Denotes a variable argument list of specific type
    /// </summary>
    class ScrVarArgListType{}
}
